From 861f4e37dd4f0f14f295db1d84f4dc902b308368 Mon Sep 17 00:00:00 2001 From: robertl Date: Sun, 26 Apr 2009 04:13:06 +0000 Subject: [PATCH] Erez Zuler adds support for Naviguide. --- Makefile.in | 2 +- cet_util.c | 27 ++ defs.h | 1 + jeeps/gpsdatum.h | 3 + jeeps/gpsmath.c | 69 +++++ jeeps/gpsmath.h | 4 + naviguide.c | 418 ++++++++++++++++++++++++++++ reference/route/naviguide-route.twl | Bin 0 -> 1539 bytes reference/route/naviguide.gpx | 96 +++++++ testo | 6 + vecs.c | 8 +- 11 files changed, 632 insertions(+), 2 deletions(-) create mode 100755 naviguide.c create mode 100755 reference/route/naviguide-route.twl create mode 100644 reference/route/naviguide.gpx diff --git a/Makefile.in b/Makefile.in index 6e072854a..855369caa 100644 --- a/Makefile.in +++ b/Makefile.in @@ -62,7 +62,7 @@ ALL_FMTS=$(MINIMAL_FMTS) gtm.o gpsutil.o pcx.o cetus.o copilot.o \ navilink.o mtk_logger.o ik3d.o osm.o destinator.o exif.o vidaone.o \ igo8.o gopal.o humminbird.o mapasia.o gnav_trl.o navitel.o ggv_ovl.o \ jtr.o sbp.o sbn.o mmo.o skyforce.o itracku.o v900.o \ - pocketfms_bc.o pocketfms_fp.o + pocketfms_bc.o pocketfms_fp.o naviguide.o FMTS=@FMTS@ diff --git a/cet_util.c b/cet_util.c index 4f754c550..205c23d25 100644 --- a/cet_util.c +++ b/cet_util.c @@ -53,8 +53,10 @@ static int cet_output = 0; #include "cet/ansi_x3_4_1968.h" #include "cet/iso_8859_1.h" +#include "cet/iso_8859_8.h" #include "cet/iso_8859_15.h" #include "cet/cp1252.h" +#include "cet/cp1255.h" /* %%% short hand strings transmission for main character sets %%% */ @@ -70,6 +72,18 @@ cet_str_iso8859_1_to_utf8(const char *src) return cet_str_any_to_utf8(src, &cet_cs_vec_iso_8859_1); } +char * +cet_str_utf8_to_iso8859_8(const char *src) +{ + return cet_str_utf8_to_any(src, &cet_cs_vec_iso_8859_8); +} + +char * +cet_str_iso8859_8_to_utf8(const char *src) +{ + return cet_str_any_to_utf8(src, &cet_cs_vec_iso_8859_8); +} + char * cet_str_utf8_to_iso8859_15(const char *src) { @@ -106,12 +120,25 @@ cet_str_cp1252_to_utf8(const char *src) return cet_str_any_to_utf8(src, &cet_cs_vec_cp1252); } +char * +cet_str_utf8_to_cp1255(const char *src) +{ + return cet_str_utf8_to_any(src, &cet_cs_vec_cp1255); +} + +char * +cet_str_cp1255_to_utf8(const char *src) +{ + return cet_str_any_to_utf8(src, &cet_cs_vec_cp1255); +} short * cet_str_utf8_to_uni(const char *src, int *length) { return cet_str_any_to_uni(src, &cet_cs_vec_utf8, length); } + + /* helpers */ /* %%% %%% diff --git a/defs.h b/defs.h index 521ae464c..3564f0901 100644 --- a/defs.h +++ b/defs.h @@ -862,6 +862,7 @@ char * get_filename(const char *fname); /* extract the filename portion */ #define CET_NOT_CONVERTABLE_DEFAULT '$' #define CET_CHARSET_ASCII "US-ASCII" #define CET_CHARSET_UTF8 "UTF-8" +#define CET_CHARSET_HEBREW "CP1255" #define CET_CHARSET_MS_ANSI "MS-ANSI" #define CET_CHARSET_LATIN1 "ISO-8859-1" diff --git a/jeeps/gpsdatum.h b/jeeps/gpsdatum.h index 005aeb0a7..7cbe23ec1 100644 --- a/jeeps/gpsdatum.h +++ b/jeeps/gpsdatum.h @@ -44,6 +44,8 @@ GPS_OEllipse GPS_Ellipse[]= { "WGS66", 6378145.000, 298.25 }, { "WGS72", 6378135.000, 298.26 }, { "WGS84", 6378137.000, 298.257223563 }, + { "Clarke 1880(Benoit)", 6378300.789,293.4663155389811 }, + }; @@ -183,6 +185,7 @@ GPS_ODatum GPS_Datum[]= /* 121 */ { "Sweden", 4, 424.3, -80.5, 613.1 }, /* 122 */ { "GDA 94", 21, 0, 0, 0 }, /* 123 */ { "CH-1903", 4, 674, 15, 405 }, +/*124 */ { "Palestine 1923", 27, -235, -85, 264}, { NULL, 0, 0, 0, 0 } }; diff --git a/jeeps/gpsmath.c b/jeeps/gpsmath.c index 35527309f..e0c31e118 100644 --- a/jeeps/gpsmath.c +++ b/jeeps/gpsmath.c @@ -733,6 +733,75 @@ void GPS_Math_Swiss_EN_To_WGS84(double E, double N, double *lat, double *lon) } +/* @func int32 GPS_Math_WGS84_To_ICS_EN ****************************** +** +** Convert WGS84 latitude and longitude to +** Israeli old Grid Eastings and Northings +** ( Israeli Cassini Soldner ) +** +** @param [r] phi [double] WGS84 latitude (deg) +** @param [r] lambda [double] WGS84 longitude (deg) +** @param [w] E [double *] ICS easting (metres) +** @param [w] N [double *] ICS northing (metres) +** +** @return [void] +************************************************************************/ + +int32 GPS_Math_WGS84_To_ICS_EN(double lat, double lon, double *E, + double *N) +{ + const double phi0 = 31.734090; + const double lambda0 = 35.212060; + const double E0 = 170251.0; + const double N0 = 1126868.0; + double phi, lambda, alt, a, b; + + if (lat < 29.333) return 0; + if (lat > 33.28) return 0; + if (lon < 34.18) return 0; + if (lon > 37.67) return 0; + + a = GPS_Ellipse[27].a; + b = a - (a / GPS_Ellipse[27].invf); + + GPS_Math_WGS84_To_Known_Datum_M(lat, lon, 0, &phi, &lambda, &alt, 124); + GPS_Math_Swiss_LatLon_To_EN(phi, lambda, E, N, phi0, lambda0, E0, N0, a, b); + + return 1; +} + + +/* @GPS_Math_ICS_EN_To_WGS84 ***************************************** +** +** Convert WGS84 latitude and longitude to +** Israeli Oldl Grid Eastings and Northings +** +** @param [r] E [double] ICS easting (metres) +** @param [r] N [double] ICS northing (metres) +** @param [w] lat [double *] WGS84 latitude (deg) +** @param [w] lon [double *] WGS84 longitude (deg) +** +** @return [void] +************************************************************************/ +void GPS_Math_ICS_EN_To_WGS84(double E, double N, double *lat, double *lon) +{ + const double phi0 = 31.734090; + const double lambda0 = 35.212060; + const double E0 = 170251.0; + const double N0 = 1126868.0; + double phi, lambda, alt, a, b; + + + a = GPS_Ellipse[27].a; + b = a - (a / GPS_Ellipse[27].invf); + + GPS_Math_Swiss_EN_To_LatLon(E, N, &phi, &lambda, phi0, lambda0, E0, N0, a, b); + GPS_Math_Known_Datum_To_WGS84_M(phi, lambda, 0, lat, lon, &alt, 124); +} + + + + /* @func GPS_Math_EN_To_LatLon ************************************** ** ** Convert Eastings and Northings to latitude and longitude diff --git a/jeeps/gpsmath.h b/jeeps/gpsmath.h index 5de8a940e..dbd8b51a5 100644 --- a/jeeps/gpsmath.h +++ b/jeeps/gpsmath.h @@ -128,6 +128,10 @@ void GPS_Math_Swiss_EN_To_LatLon(double E, double N, double *phi, double *lambda, double phi0, double lambda0, double E0, double N0, double a, double b); +int32 GPS_Math_WGS84_To_ICS_EN(double lat, double lon, double *E, + double *N); +void GPS_Math_ICS_EN_To_WGS84(double E, double N, double *lat, double *lon); + int32 GPS_Math_WGS84_To_Swiss_EN(double phi, double lambda, double *E, double *N); void GPS_Math_Swiss_EN_To_WGS84(double E, double N, double *lat, double *lon); diff --git a/naviguide.c b/naviguide.c new file mode 100755 index 000000000..bf529874f --- /dev/null +++ b/naviguide.c @@ -0,0 +1,418 @@ +/* + Naviguide Routes + + + Copyright (C) 2009 Erez Zuler + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#include "csv_util.h" +#include "jeeps/gpsmath.h" +#include +#include + +#define MYNAME "Naviguide" + + + + + + +/************* Specific Naviguide data formats ****************/ + +/* Naviguide file header */ +typedef struct { + gbuint16 nof_wp; /* Little endean format */ + char pad1[6]; /* 0xff, 0xff, 0x01, 0x00, 0x06, 0x00 */ + char signature[9]; /* cWaypoint */ + char pad2[4]; /* 0x01, 0x00, 0x00, 0x00 */ +} ng_file_header_t; + +/* Naviguide waypoint/rout data */ +typedef struct{ + char pad1[8]; /* 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 */ + /* coordination are in old israeli grid */ + gbuint32 East; + gbuint32 North; + char pad2[2]; /* 0x01, 0x01 */ + gbuint32 Alt; + char CommentLength; +} ng_wp_data_t; + +typedef struct{ + char pad1[2]; /* 0x01, 0x80 */ + gbuint16 next_wp; + char pad2[2]; /* 0x00, 0x00 */ +} ng_next_wp_t; + +typedef struct { + unsigned char chHeaderLen; + char strName[255]; + ng_wp_data_t wp_data; +} ng_wp_no_comment_t; + + +/* Global variables */ + +static gbfile *file_in, *file_out; +static short_handle mkshort_handle; +static gbuint16 nof_wp; +static route_head *rte_head; +static ng_file_header_t ng_file_header; +static ng_wp_no_comment_t WPNC; +static ng_next_wp_t ng_next_wp; +static char strComment[101]; + +/* Process options */ +/* wp - process only waypoints */ +/* rte - process as route */ +/* wprte - Process waypoints and route */ +static char *process = NULL; +static char *reorder = NULL; +static int process_rte = 1; +static int reorder_wp = 0; + +static char temp_short_name[5]; + + + + +/* Forward declarations */ +static void ng_read_file_header(void); + +static +arglist_t ng_args[] = { + {"output", &process, "'wp' - Create waypoint file , 'rte' - Create route file", + "rte", ARGTYPE_STRING, ARG_NOMINMAX}, + {"reorder", &reorder, "'n' - Keep the existing wp name, 'y' - rename waypoints", + "n", ARGTYPE_STRING, ARG_NOMINMAX}, + + ARG_TERMINATOR +}; + +/*===================Utilities ==========================================*/ + +static void +ng_convert_datum(waypoint *wpt) +{ + double lat, lon, east, north, alt; + + east = (double) WPNC.wp_data.East; + north = (double) WPNC.wp_data.North; + alt = (double) WPNC.wp_data.Alt; + + GPS_Math_ICS_EN_To_WGS84(east, north, &lat, &lon); + wpt->latitude = lat; + wpt->longitude = lon; + wpt->altitude = alt; +} + + + +/*=================== File read/write utilities ==========================================*/ + +static void +ng_fwrite_wp_data (char *s, char *d, ng_wp_data_t *wp_data, gbfile *f) { + int i; + char z[50]; + + memset (z, 0, 50); + + i = (s == NULL) ? 0 : strlen (s); + gbfwrite (&i, 1, 1, f); + gbfwrite (s, 1, i, f); + + gbfwrite (&wp_data->pad1[0], 8, 1, f); + gbfputint32 (wp_data->East, f); + gbfputint32 (wp_data->North, f); + gbfwrite (&wp_data->pad2[0], 2, 1, f); + gbfputint32 (wp_data->Alt, f); + + i = (d == NULL) ? 0 : strlen (d); + gbfwrite (&i, 1, 1, f); + gbfwrite (d, 1, i, f); + gbfwrite (z, 44, 1, f); +} + +static void +ng_fwrite_next_wp (ng_next_wp_t *nwp, gbfile *f) { + gbfwrite (nwp->pad1, 2, 1, f); + gbfputint16 (nwp->next_wp, f); + gbfwrite (nwp->pad2, 2, 1, f); +} + +static void +ng_fread_wp_data (char *d, ng_wp_no_comment_t *wpnc, gbfile *f) { + + int i; + + gbfread (&wpnc->chHeaderLen ,sizeof (wpnc->chHeaderLen), 1, f); + gbfread (&wpnc->strName, wpnc->chHeaderLen, 1, f); + wpnc->strName[wpnc->chHeaderLen] = 0; + + + gbfread (&wpnc->wp_data, 8, 1, f); + wpnc->wp_data.East = gbfgetint32 (f); + wpnc->wp_data.North = gbfgetint32 (f); + gbfread (&wpnc->wp_data.pad2,2, 1, f); + wpnc->wp_data.Alt = gbfgetint32 (f); + gbfread (&wpnc->wp_data.CommentLength, 1, 1, f); + i = (int)wpnc->wp_data.CommentLength; + + + /* Read the comment field */ + gbfread (d, i + 44, 1, f); + +} + +static void +ng_fread_next_wp (ng_next_wp_t *nwp, gbfile *f) { + gbfread (&nwp->pad1, 2, 1, f); + nwp->next_wp = gbfgetint16 (f); + gbfread (&nwp->pad2, 2, 1, f); +} + +/* =================== Write data functions ====================================*/ + +static void +ng_fill_header_default (void) { + ng_file_header_t default_header = { + 0x00, + {0xff, 0xff, 0x01, 0x00, 0x09, 0x00}, + {'C', 'W', 'a', 'y', 'P', 'o', 'i', 'n', 't'}, + {0x01, 0x00, 0x00, 0x00}, + }; + + ng_file_header =default_header; + +} + + +static void +ng_fill_waypoint_default (void) { + ng_wp_data_t default_wp = { + {0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00}, + 0, + 0, + {0x01, 0x01}, + 0, + 0x00, + + }; + + ng_next_wp_t default_ng_next_wp = { + {0x01, 0x80}, + 0, + {0x00, 0x00}, + }; + + WPNC.wp_data = default_wp; + ng_next_wp = default_ng_next_wp; +} + + +static void +ng_waypt_rd (const waypoint * wpt) { + char * s = NULL; + + char z[50]; + double lat, lon; + static int current_wp_ix=0; + + memset (z, 0, 50); + current_wp_ix++; + ng_fill_waypoint_default(); + + if (!GPS_Math_WGS84_To_ICS_EN(wpt->latitude, wpt->longitude, &lon, &lat)) { + fatal(MYNAME ": Waypoint %d is out of the israeli grid area", current_wp_ix); + } + + WPNC.wp_data.North = (gbuint32)lat; + WPNC.wp_data.East = (gbuint32)lon; + + if (reorder_wp) { + sprintf (temp_short_name, "A%03d", current_wp_ix); + s = temp_short_name; + } + + else + s = wpt->shortname; + + ng_fwrite_wp_data (s, wpt->description, &WPNC.wp_data, file_out); + + + /* if not Last WP, write the next one index */ + + if (nof_wp > current_wp_ix) { + ng_next_wp.next_wp = current_wp_ix + 1; + + ng_fwrite_next_wp (&ng_next_wp, file_out); + + } +} + +static void +header_write (void) { + ng_file_header.nof_wp = nof_wp; + gbfputint16 (nof_wp, file_out); + gbfwrite(&ng_file_header.pad1[0], 19, 1, file_out); + +} + + +static void +data_write (void) { + nof_wp = waypt_count(); + if (nof_wp) { + header_write (); + waypt_disp_all(ng_waypt_rd); + } + else { + nof_wp = route_waypt_count(); + if (nof_wp) { + header_write (); + route_disp_all(NULL, NULL, ng_waypt_rd); + } + } +} + + +static void +wr_init(const char *fname) { + file_out = gbfopen_le(fname, "wb", MYNAME); + ng_fill_header_default (); + if (NULL != reorder) + if (!case_ignore_strcmp(reorder, "y")) {reorder_wp = 1;} + +} + +static void +wr_deinit () { + gbfclose(file_out); + + +} + +/*=========================== Read data functions ==================================*/ + +static void +rd_init(const char *fname) +{ + file_in = gbfopen_le(fname, "rb", MYNAME); + + mkshort_handle = mkshort_new_handle(); + ng_read_file_header(); + + if (NULL != process) { + if (!case_ignore_strcmp(process, "wp")) {process_rte = 0;} + if (!case_ignore_strcmp(process, "rte")) {process_rte = 1;} + } + + +} + +static void +rd_deinit(void) +{ + gbfclose(file_in); + file_in = NULL; + mkshort_del_handle(&mkshort_handle); +} + + + +static void +ng_read_file_header(void) +{ + + nof_wp = gbfgetint16 (file_in); + gbfread (&ng_file_header.pad1[0], 19, 1, file_in); + ng_file_header.nof_wp = nof_wp; + + + if (strncmp ("CWayPoint", ng_file_header.signature, 9)) + fatal ("\nInvalid Naviguide file format\n"); + + +} + +static void +data_read(void) +{ + int n, i; + waypoint *wpt_tmp; + + if (process_rte) { + rte_head = route_head_alloc(); + rte_head->rte_waypt_ct = nof_wp; + route_add_head(rte_head); + } + + for (n = 0; n < nof_wp; ++n) { + + wpt_tmp = waypt_new (); + + /* Read waypoint data */ + + ng_fread_wp_data (strComment, &WPNC, file_in); + + + if (n < nof_wp - 1) { + /* + gbfread (&ng_next_wp.pad1[0], 2, 1, file_in); + ng_next_wp.next_wp = gbfgetint16 (file_in); + gbfread (&ng_next_wp.pad2[0], 2, 1, file_in); + */ + ng_fread_next_wp (&ng_next_wp, file_in); + + } + /* Clear commas form the comment for CSV file commonality */ + for (i = 0; i shortname = xstrdup (WPNC.strName); + wpt_tmp->description = xstrdup (strComment); + + if (process_rte) + route_add_wpt(rte_head, wpt_tmp); + else + waypt_add(wpt_tmp); + } +} /* data_read */ + + + +ff_vecs_t ng_vecs = { + ff_type_file, + FF_CAP_RW_WPT, + rd_init, + wr_init, + rd_deinit, + wr_deinit, + data_read, + data_write, + NULL, + ng_args, + //CET_CHARSET_ASCII, 0 /* CET-REVIEW */ + CET_CHARSET_HEBREW, 0 +}; diff --git a/reference/route/naviguide-route.twl b/reference/route/naviguide-route.twl new file mode 100755 index 0000000000000000000000000000000000000000..2ce57d8eebc537ceb0516255c6a8e229b4998959 GIT binary patch literal 1539 zcmbW%J4?e*6bJBguhqVMv_?e{F)m6w*rX31qd17*;O6XRvFM_MAehaM_8jjo3y{2os!8+_Pi(@o^^8{BAjur_H3;pGo)hDz9Y1wNI7kNc3BD5lD z+6{;If}++hv=V9iw;YahirRqCmPpg?I9wWvT2yGuq&?qrXqu!YKE9l0U3a^04Ge}J zX2mcYeBBjtZFFO*?;ID}Drq^?HWz7^q4yO8nU(n0OoO!A6NkO5qLvhzEJzi#+Jd4s zC^XrMvquh7^NQM#&}1ue4;-vHMQvDUvK3{#dFQi=+KA9(E4EO}%#fCD+g?v^ed^s; z$JL#V{f+t1!>kl$@dBE%CJ8*q_B8RKr69 + + + + + + 0.000000 + A001 + תחילת מסלול + תחילת מסלול + + + 0.000000 + A002 + + + 0.000000 + A003 + + + 0.000000 + A004 + + + 0.000000 + A005 + + + 0.000000 + A006 + + + 0.000000 + A007 + כניסה לשטח + כניסה לשטח + + + 0.000000 + A008 + + + 0.000000 + A009 + + + 0.000000 + A010 + + + 0.000000 + A011 + + + 0.000000 + A012 + + + 0.000000 + A013 + + + 0.000000 + A014 + + + 0.000000 + A015 + צומת עם שביל ירוק + צומת עם שביל ירוק + + + 0.000000 + A016 + + + 0.000000 + A017 + + + 0.000000 + A018 + + + 0.000000 + A019 + מערה + מערה + + + diff --git a/testo b/testo index 749b8e58d..81a64f7d4 100755 --- a/testo +++ b/testo @@ -1593,4 +1593,10 @@ compare ${REFERENCE}/v900_basic_mode.gpx ${TMPDIR}/v900_basic_mode.gpx gpsbabel -i v900 -f ${REFERENCE}/v900_advanced_mode.csv -o gpx -F ${TMPDIR}/v900_advanced_mode.gpx compare ${REFERENCE}/v900_advanced_mode.gpx ${TMPDIR}/v900_advanced_mode.gpx +# +# Naivguide +# +gpsbabel -i naviguide -f ${REFERENCE}/route/naviguide-route.twl -o gpx -F ${TMPDIR}/naviguide.gpx +compare ${REFERENCE}/route/naviguide.gpx ${TMPDIR}/naviguide.gpx + exit 0 diff --git a/vecs.c b/vecs.c index dd9e35146..839b9a34a 100644 --- a/vecs.c +++ b/vecs.c @@ -153,6 +153,7 @@ extern ff_vecs_t jtr_vecs; extern ff_vecs_t itracku_vecs; extern ff_vecs_t itracku_fvecs; extern ff_vecs_t sbp_vecs; +extern ff_vecs_t ng_vecs; extern ff_vecs_t sbn_vecs; extern ff_vecs_t mmo_vecs; extern ff_vecs_t skyforce_vecs; @@ -919,7 +920,12 @@ vecs_t vec_list[] = { "Columbus/Visiontac V900 files (.csv)", NULL }, - + { + &ng_vecs, + "naviguide", + "Naviguide binary route file (.twl)", + "twl" + }, #endif // MAXIMAL_ENABLED { -- 2.30.2